package cmd

import (
	"context"
	"github.com/deckarep/golang-set"
	"github.com/spf13/cobra"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	"log"
	"github.com/tluo-github/super-job/helpers/ssh"
	restclient "k8s.io/client-go/rest"

)

var namespace string
var config string
var username string
var endpointCmd = &cobra.Command{
	Use:   "endpoint",
	Short: "k8s endpoint check tool",
	Long: `k8s endpoint check'`,
	Run: func(cmd *cobra.Command, args []string)  {
		// Do Stuff Here
		log.Println("endpoint command run")
		runEndpointCommand(namespace,config,username,password)
	},
}

func init() {
	endpointCmd.Flags().StringVarP(&namespace, "namespace", "n", "", "k8s namespace")
	endpointCmd.Flags().StringVarP(&config, "config", "c", "", "k8s config file")
	endpointCmd.Flags().StringVarP(&password, "password", "p", "", "password")
	endpointCmd.Flags().StringVarP(&username, "usernname", "u", "", "username")

	rootCmd.AddCommand(endpointCmd)
}

func loadDefaultKubectlConfig() (*restclient.Config, error) {
	config, err := clientcmd.NewDefaultClientConfigLoadingRules().Load()
	if err != nil {
		return nil, err
	}

	return clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
}
func guessClientConfig() (*restclient.Config, error) {
	// Try in cluster config first
	if inClusterCfg, err := rest.InClusterConfig(); err == nil {
		return inClusterCfg, nil
	}

	// in cluster config failed. Reading default kubectl config
	return loadDefaultKubectlConfig()
}

func runEndpointCommand(namespace string,k8sconfig string,username string, password string) {
	var config *rest.Config
	var err error
	if len(k8sconfig) >0 {
		config, err = clientcmd.BuildConfigFromFlags("", k8sconfig)
	} else {
		config, err = guessClientConfig()
	}
	if err != nil {
		panic(err.Error())
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		log.Fatalln(err)
	} else {
		log.Println("connect k8s success")
	}

	endpoints ,err :=clientset.CoreV1().Endpoints(namespace).List(metav1.ListOptions{})
	if err != nil {
		log.Fatal(err)
	}
	address := []string{}
	for _,endpoint:= range endpoints.Items {
		for _,x:= range endpoint.Subsets{
			for _,y := range x.NotReadyAddresses{
				log.Printf("%s Not Read Address :%s", endpoint.Name,y.IP)
				address = append(address,y.IP)
			}
		}
	}
	if len(address) <= 0 {
		return
	}
	nodes := mapset.NewSet()
	pods, err := clientset.CoreV1().Pods(namespace).List(metav1.ListOptions{})
	if err != nil {
		log.Fatal(err)
	}
	for _,pod:= range pods.Items {
		ip := pod.Status.PodIP
		for _, address := range address {
			if address == ip{
				nodes.Add(pod.Status.HostIP)
				log.Printf("pod: %s ip:%s node:%s ,endpoints Not Read", pod.Name,ip,pod.Status.HostIP)
				break
			}
		}
	}
	it := nodes.Iterator()

	for elem := range it.C {
		ip := elem.(string)
		log.Printf("node ip : %s, username: %s , password:%s",ip,username,password)
		client := ssh.Client{
			SshConfig:      ssh.SshConfig{
				User:         username,
				Password:     password,
				Host:         ip,
				Port:         "22",
				IdentityFile: "",
			},
			Stdout:         log.Writer(),
			Stderr:         log.Writer(),
			ConnectRetries: 0,
		}
		err = client.Connect()
		if err != nil{
			log.Println(err)
			return
		}
		err = client.Run(context.Background(),ssh.Command{
			Environment: nil,
			Command:     []string{"/bin/sh"},
			Stdin:       "systemctl restart kubelet",
		})
		if err != nil{
			log.Println(err)
		}

	}
	log.Println("ok")

}
